package com.devunion.bogdan.model.project;

import org.apache.log4j.Logger;

import com.devunion.bogdan.model.event.ProjectListener;
import com.devunion.bogdan.model.event.ProjectEvent;
import com.devunion.bogdan.model.project.dao.ProjectDao;
import com.devunion.bogdan.model.project.dao.PaperDao;
import com.devunion.bogdan.model.project.dao.OntologyPropertyDao;
import com.devunion.bogdan.spring.Context;

import javax.swing.event.EventListenerList;

/**
 * @author Viktar Liaskovich
 */
public class ProjectManager {
    private static Logger log = Logger.getLogger(ProjectManager.class);

    private Project currentProject;
    protected EventListenerList listenerList = new EventListenerList();

    private static ProjectManager instance;
    private ProjectDao projectDao;
    private PaperDao paperDao;
    private OntologyPropertyDao ontologyPropertyDao;

    // Singleton
    private ProjectManager() {
        projectDao = (ProjectDao) Context.getContext().getBean("projectDao");
        paperDao = (PaperDao) Context.getContext().getBean("paperDao");
        ontologyPropertyDao = (OntologyPropertyDao) Context.getContext().getBean("ontologyPropertyDao");
        RelativePathConverter relativePathConverter = (RelativePathConverter) Context.getContext().getBean("relativePathConverter");
        ImageHelper.getInstance().setRelativePathConverter(relativePathConverter);
    }

    public Project getProjectForPaper(Long paperId) {
        return paperDao.getPorject(paperId);
    }

    public static ProjectManager getInstance() {
        if (instance == null) {
            instance = new ProjectManager();
        }

        return instance;
    }

    public Project loadProject(Project project) throws ProjectLoadingException {

        ImageHelper.getInstance().setProjectName(project.getName());

        fireProjectCreatedEvent(new ProjectEvent(this, project));

        return project;
    }

    public Project loadProject(Long projectKey) throws ProjectLoadingException {
        return loadProject(projectDao.getByKey(projectKey));
    }

    public Project createNewProject(String projectName) throws ProjectCreationException, ProjectSavingException {

        Project project = new Project(projectName);

//        fireProjectCreatedEvent(new ProjectEvent(this, currentProject));

        saveCurrentProject();

        ImageHelper.getInstance().setProjectName(projectName);

        return project;
    }

    public void setCurrentProject(Project currentProject) {
        this.currentProject = currentProject;
    }

    public Project getCurrentProject() {
        return currentProject;
    }

    public boolean isProjectOpened() {
        return currentProject != null;
    }

    public void saveCurrentProject() throws ProjectSavingException {
        if (currentProject == null) {
            return;
        }

//        for (Paper paper : currentProject.getEntries()) {
//            for (Page page : paper.getPages()) {
//                page.getImage();
//            }
//        }

//        for (Ontology ontology : currentProject.getOntologies()) {
//            for (OntologyProperty property : ontology.getOntologyProperties()) {
//                ontologyPropertyDao.saveOrUpdate(property);
//            }
//        }

        projectDao.saveOrUpdate(currentProject);

        log.debug("Current project '" + currentProject.toString() + "' is saved");
    }

    public void closeProject() throws ProjectSavingException {
        saveCurrentProject();

        currentProject.close();

        ImageHelper.getInstance().setProjectName(null);

        final ProjectEvent projectEvent = new ProjectEvent(this, currentProject);

        currentProject = null;

        fireProjectClosedEvent(projectEvent);
    }

    public void addProjectListener(ProjectListener listener) {
        listenerList.add(ProjectListener.class, listener);
    }

    public void removeProjectListener(ProjectListener listener) {
        listenerList.remove(ProjectListener.class, listener);
    }

    public ProjectListener[] getProjectListeners() {
        return listenerList.getListeners(ProjectListener.class);
    }

    protected void fireProjectCreatedEvent(ProjectEvent e) {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();

        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = 0; i < listeners.length; i++) {
            if (listeners[i] == ProjectListener.class) {
                ((ProjectListener) listeners[i + 1]).projectCreated(e);
            }
        }
    }

    protected void fireProjectClosedEvent(ProjectEvent e) {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();

        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 1; i >= 0; i--) {
            if (listeners[i] == ProjectListener.class) {
                ((ProjectListener) listeners[i + 1]).projectClosed(e);
            }
        }
    }
}
